package user

import (
	"context"
	"git.mycaigou.com/gfyx/common/rpc_client"
	userDto "git.mycaigou.com/gfyx/micro-gfyx-mp-api/http_server/dto/user"
	"git.mycaigou.com/gfyx/micro-gfyx-mp-api/infrastructure/common/constants"
	microGfyxUserService "git.mycaigou.com/gfyx/micro-gfyx-mp-api/proto/micro_gfyx_user_service_proto/micro-gfyx-user-service"
	baseUserService "git.mycaigou.com/gfyx/micro-gfyx-mp-api/service/base/user/user_service"
	"time"
)

type userRepository struct{}

// NewUserRepository
// 构造函数
func NewUserRepository() baseUserService.UserRepositoryIface {
	return &userRepository{}
}

// MpBindUser
// 小程序账号绑定
func (r *userRepository) MpBindUser(ctx context.Context, openId, mobile string, unionId string) (*baseUserService.LoginInfo, error) {
	request := &microGfyxUserService.BindUserRequest{
		Openid:  openId,
		Mobile:  mobile,
		Type:    1,
		UnionId: unionId,
	}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return nil, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewUserLoginServiceClient(conn)
	res, err := client.BindUser(ctx, request)
	if err != nil {
		return nil, err
	}

	if res == nil {
		return nil, nil
	}

	loginInfo := &baseUserService.LoginInfo{}
	if res.UserInfo != nil {
		loginInfo.UserInfo = &baseUserService.UserInfo{
			Id:            res.UserInfo.UserId,
			UserName:      res.UserInfo.UserName,
			UserId:        res.UserInfo.UserUid,
			MpOpenId:      res.UserInfo.MpOpenId,
			UserCode:      res.UserInfo.UserCode,
			GlobalUserUid: res.UserInfo.Uid,
			Mobile:        res.UserInfo.MobilePhone,
			MpUnionId:     res.UserInfo.MpUnionId,
		}
	}

	if len(res.TenantInfo) != 0 {
		loginInfo.TenantList = make([]*baseUserService.TenantInfo, 0)
		loginInfo.TenantList = append(loginInfo.TenantList, &baseUserService.TenantInfo{
			TenantCode:         res.TenantInfo[0].TenantCode,
			TenantName:         res.TenantInfo[0].TenantName,
			ClueRadarPayStatus: res.TenantInfo[0].ClueRadarPayStatus,
		})
	}

	loginInfo.Token = res.Token
	return loginInfo, nil
}

// MpLogin
// 小程序登录
func (r *userRepository) MpLogin(ctx context.Context, openId string, unionId string) (*baseUserService.LoginInfo, error) {
	request := &microGfyxUserService.LoginByOpenIdRequest{Openid: openId, Type: 1, UnionId: unionId}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return nil, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewUserLoginServiceClient(conn)
	res, err := client.LoginByOpenId(ctx, request)
	if err != nil {
		return nil, err
	}

	if res == nil {
		return nil, nil
	}

	loginInfo := baseUserService.LoginInfo{}
	if res.UserInfo != nil {
		loginInfo.UserInfo = &baseUserService.UserInfo{
			Id:            res.UserInfo.UserId,
			UserName:      res.UserInfo.UserName,
			UserId:        res.UserInfo.UserUid,
			UserCode:      res.UserInfo.UserCode,
			MpOpenId:      res.UserInfo.MpOpenId,
			GlobalUserUid: res.UserInfo.Uid,
			Mobile:        res.UserInfo.MobilePhone,
			MpUnionId:     res.UserInfo.MpUnionId,
		}
	}

	if len(res.TenantInfo) != 0 {
		loginInfo.TenantList = make([]*baseUserService.TenantInfo, 0)
		loginInfo.TenantList = append(loginInfo.TenantList, &baseUserService.TenantInfo{
			TenantCode:         res.TenantInfo[0].TenantCode,
			TenantName:         res.TenantInfo[0].TenantName,
			ClueRadarPayStatus: res.TenantInfo[0].ClueRadarPayStatus,
		})
	}

	loginInfo.Token = res.Token

	return &loginInfo, nil
}

// SmsLogin
// 小程序登录
func (r *userRepository) SmsLogin(ctx context.Context, request *microGfyxUserService.LoginByMobileSmsRequest) (*baseUserService.LoginInfo, error) {
	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return nil, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewUserLoginServiceClient(conn)
	res, err := client.LoginByMobileSms(ctx, request)
	if err != nil {
		return nil, err
	}

	if res == nil {
		return nil, nil
	}

	loginInfo := baseUserService.LoginInfo{}
	if res.UserInfo != nil {
		loginInfo.UserInfo = &baseUserService.UserInfo{
			Id:            res.UserInfo.UserId,
			UserName:      res.UserInfo.UserName,
			UserId:        res.UserInfo.UserUid,
			UserCode:      res.UserInfo.UserCode,
			MpOpenId:      res.UserInfo.MpOpenId,
			GlobalUserUid: res.UserInfo.Uid,
			Mobile:        res.UserInfo.MobilePhone,
			MpUnionId:     res.UserInfo.MpUnionId,
		}
	}

	if len(res.TenantInfo) != 0 {
		loginInfo.TenantList = make([]*baseUserService.TenantInfo, 0)
		loginInfo.TenantList = append(loginInfo.TenantList, &baseUserService.TenantInfo{
			TenantCode:         res.TenantInfo[0].TenantCode,
			TenantName:         res.TenantInfo[0].TenantName,
			ClueRadarPayStatus: res.TenantInfo[0].ClueRadarPayStatus,
		})
	}

	loginInfo.Token = res.Token

	return &loginInfo, nil
}

// GetUserInfo
// 获取用户信息
func (r *userRepository) GetUserInfo(ctx context.Context, params *baseUserService.GetUserInfoParams) (*baseUserService.LoginInfo, error) {
	request := &microGfyxUserService.GetUserInfoRequest{
		Type:  2,
		Param: params.GlobalUId,
	}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return nil, err
	}
	defer func() {
		_ = conn.Close()
	}()

	client := microGfyxUserService.NewUserInfoServiceClient(conn)
	res, err := client.GetUserInfo(ctx, request)
	if err != nil {
		return nil, err
	}

	if res == nil {
		return nil, nil
	}

	loginInfo := &baseUserService.LoginInfo{}
	if res.UserInfo != nil {
		loginInfo.UserInfo = &baseUserService.UserInfo{
			Id:            res.UserInfo.Id,
			UserName:      res.UserInfo.UserName,
			UserCode:      res.UserInfo.UserCode,
			UserId:        res.UserInfo.UserUid,
			MpOpenId:      res.UserInfo.MpOpenId,
			GlobalUserUid: res.UserInfo.Uid,
			Mobile:        res.UserInfo.MobilePhone,
			MpUnionId:     res.UserInfo.MpUnionId,
		}
	}

	if len(res.TenantInfo) != 0 {
		loginInfo.TenantList = make([]*baseUserService.TenantInfo, 0)
		loginInfo.TenantList = append(loginInfo.TenantList, &baseUserService.TenantInfo{
			TenantCode:         res.TenantInfo[0].TenantCode,
			TenantName:         res.TenantInfo[0].TenantName,
			ClueRadarPayStatus: res.TenantInfo[0].ClueRadarPayStatus,
		})
	}

	return loginInfo, nil
}

// VerifyToken
// 验证token
func (r *userRepository) VerifyToken(ctx context.Context, token string) (info *baseUserService.UserInfo, tenantInfo *baseUserService.TenantInfo, err error) {
	request := &microGfyxUserService.VerifyTokenRequest{Token: token}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return nil, nil, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewUserLoginServiceClient(conn)
	res, err := client.VerifyToken(ctx, request)

	if err != nil {
		return nil, nil, err
	}
	if res == nil {
		return nil, nil, nil
	}

	userInfo := &baseUserService.UserInfo{}
	if res.UserInfo != nil {
		userInfo.Id = res.UserInfo.UserId
		userInfo.UserId = res.UserInfo.UserUid
		userInfo.GlobalUserUid = res.UserInfo.Uid
		userInfo.MpOpenId = res.UserInfo.MpOpenId
		userInfo.UserName = res.UserInfo.UserName
		userInfo.Mobile = res.UserInfo.MobilePhone
		userInfo.UserCode = res.UserInfo.UserCode
	}

	tenantInfo = &baseUserService.TenantInfo{}
	if len(res.TenantInfo) != 0 {
		tenantInfo.TenantName = res.TenantInfo[0].GetTenantName()
		tenantInfo.TenantCode = res.TenantInfo[0].GetTenantCode()
		tenantInfo.ClueRadarPayStatus = res.TenantInfo[0].ClueRadarPayStatus
	}

	return userInfo, tenantInfo, nil
}

func (r *userRepository) TestTenantDbEnable(ctx context.Context, s string) (string, error) {
	//request := &micro_gfyx_oppty_service.TestTenantDbEnableRequest{
	//	UserGuid: s,
	//}
	//
	//fn := func(ctx context.Context, clientConn *grpc.ClientConn) (interface{}, error) {
	//	client := micro_gfyx_oppty_service.NewReportServiceClient(clientConn)
	//	res, err := client.TestTenantDbEnable(ctx, request)
	//
	//	if err != nil {
	//		return nil, err
	//	}
	//
	//	return res, nil
	//}
	//
	//res := &micro_gfyx_oppty_service.TestTenantDbEnableResponse{}
	//errs := rpc_client.New(ctx).GetTenantClientConn("micro-gfyx-oppty-service").Do(fn, res, request)
	//
	//if errs != nil {
	//	return "", errs[0]
	//}
	//
	//if res == nil {
	//	return "", nil
	//}

	return "yes", nil
}

func (r *userRepository) SyncAllUser(ctx context.Context, tenantCode string, pagesize int32) (bool, error) {
	request := &microGfyxUserService.SyncUserRequest{TenantCode: tenantCode, Page: 0, Pagesize: pagesize}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return false, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewUserInfoServiceClient(conn)
	res, err := client.SyncAllUser(ctx, request)
	if err != nil {
		return false, err
	}
	if res == nil {
		return false, nil
	}

	return res.SyncFlag, nil
}

func (r *userRepository) SyncAllUserRoleRelation(ctx context.Context, tenantCode string, pagesize int32) (bool, error) {
	request := &microGfyxUserService.SyncAllUserRoleRelationRequest{TenantCode: tenantCode, Page: 0, Pagesize: pagesize}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return false, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewUserInfoServiceClient(conn)
	res, err := client.SyncAllUserRoleRelation(ctx, request)
	if err != nil {
		return false, err
	}

	if res == nil {
		return false, nil
	}
	return res.SyncFlag, nil
}

func (r *userRepository) SyncAllRole(ctx context.Context, tenantCode string, pagesize int32) (bool, error) {
	request := &microGfyxUserService.SyncRoleRequest{TenantCode: tenantCode, Page: 0, Pagesize: pagesize}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return false, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewRoleServiceClient(conn)
	// 超时控制
	ctx, cancel := context.WithTimeout(ctx, 120*time.Second)
	defer cancel()

	res, err := client.SyncAllRole(ctx, request)
	if err != nil {
		return false, err
	}
	if res == nil {
		return false, nil
	}
	return res.SyncFlag, nil
}

func (r *userRepository) SyncAllUserActionRightInfos(ctx context.Context, tenantCode string) (bool, error) {
	request := &microGfyxUserService.SyncAllUserActionRightInfosRequest{TenantCode: tenantCode}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return false, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewUserInfoServiceClient(conn)
	// 超时控制
	ctx, cancel := context.WithTimeout(ctx, 120*time.Second)
	defer cancel()

	res, err := client.SyncAllUserActionRightInfos(ctx, request)
	if err != nil {
		return false, err
	}

	if res == nil {
		return false, nil
	}

	return res.SyncFlag, nil
}

func (r *userRepository) SyncAllOrganizations(ctx context.Context, tenantCode string) (bool, error) {
	request := &microGfyxUserService.SyncOrganizationRequest{TenantCode: tenantCode}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return false, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewOrganizationServiceClient(conn)
	// 超时控制
	ctx, cancel := context.WithTimeout(ctx, 120*time.Second)
	defer cancel()

	res, err := client.SyncAllOrganization(ctx, request)
	if err != nil {
		return false, err
	}

	if res == nil {
		return false, nil
	}

	return res.SyncFlag, nil
}

func (r *userRepository) SyncTenantProfit(ctx context.Context, tenantCode string, syncAllTenantProfitRequest *userDto.SyncAllTenantProfitRequest) (bool, error) {
	tenantProfitList := []*microGfyxUserService.TenantProfit{}
	for _, v := range syncAllTenantProfitRequest.Profit {
		tenantProfitList = append(tenantProfitList, &microGfyxUserService.TenantProfit{
			EffectiveEndTime:   v.EffectiveEndTime,
			EffectiveStartTime: v.EffectiveStartTime,
			ProductCode:        v.ProductCode,
			ProfitName:         v.ProfitName,
			ProfitOutsideCode:  v.ProfitOutsideCode,
			ProfitOutsideUid:   v.ProfitOutsideUID,
			Uid:                v.UID,
		})
	}
	request := &microGfyxUserService.SyncTenantProfitRequest{TenantCode: tenantCode, TenantProfitList: tenantProfitList}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return false, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewUserInfoServiceClient(conn)
	// 超时控制
	ctx, cancel := context.WithTimeout(ctx, 120*time.Second)
	defer cancel()

	res, err := client.SyncTenantProfit(ctx, request)
	if err != nil {
		return false, err
	}

	if res == nil {
		return false, nil
	}

	return res.SyncFlag, nil
}

func (r *userRepository) IncrSyncUser(ctx context.Context, tenantCode, operation string, userList []baseUserService.IncrUserInfo) (bool, error) {
	request := &microGfyxUserService.IncrementSyncUserRequest{}
	request.TenantCode = tenantCode
	request.Operation = operation
	for _, info := range userList {
		incrUserInfo := &microGfyxUserService.IncrUser{}
		incrUserInfo.UserId = info.UserId
		incrUserInfo.UserUid = info.UserGuid
		incrUserInfo.UserName = info.UserName
		incrUserInfo.UserCode = info.UserCode
		incrUserInfo.MobilePhone = info.MobilePhone
		incrUserInfo.IsDisable = info.IsDisable
		incrUserInfo.Password = info.Password
		incrUserInfo.BuGuid = info.BuGuid
		request.UserList = append(request.UserList, incrUserInfo)
	}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return false, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewUserInfoServiceClient(conn)
	res, err := client.IncrementSyncUser(ctx, request)
	if err != nil {
		return false, err
	}
	if res == nil {
		return false, nil
	}

	return res.SyncFlag, nil
}

// UserApply
// 申请
func (r *userRepository) UserApply(ctx context.Context, mobile string) error {
	req := &microGfyxUserService.UserApplyRequest{
		Mobile: mobile,
	}

	conn, ctx, err := rpc_client.GetClientConn(ctx, constants.MICRO_GFYX_USER_SERVICE)
	if err != nil {
		return err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := microGfyxUserService.NewUserLoginServiceClient(conn)
	_, err = client.UserApply(ctx, req)
	if err != nil {
		return err
	}
	return nil
}
